/*
  this link list program can be used to form table for compression
  @ vishwajeet dusane
  What this program does
	 -accept file name from user
	 -build table i.e. occurence of each char in the file
	 -sort them according to the number of char in file in descending order
*/

#include<math.h>
#include<stdio.h>
#include<process.h>
#include<iostream.h>
#include<alloc.h>

struct node
{
  int ch;
  int counter;
  struct node *next;
};

/*
  this link list program can be used to form table for compression
   which is Header File can Be used by others program to use
   for Building Table
	   -occurence of char in file and number of time it does

   *it will sort the file according to the number of time it occures
   *display the table(sorted or unsorted)

  @ ISSC By
		   vishwajeet dusane

  What this
	 -build table i.e. occurence of each char in the file
	 -sort them according to the number of char in file in descending order
*/
class BuildTable
{
public:
int search(struct node **,int );
void display(struct node *);
void create(struct node **,int);
void SortTable(struct node **);
int getPosition(struct node *,int);
int getCharacter(struct node **,int);
void replaceNumber(char fname[30]);
};

 void BuildTable:: create(struct node **head,int ch)
 {
   struct node *temp=*head;

	if(*head==NULL)
	  {
	   *head=(struct node *)malloc(sizeof(struct node));
	  (*head)->next=NULL;
	(*head)->ch=ch;
	(*head)->counter=1;
	   }
	  else
	  {
	  temp=*head;
	  while(temp->next!=NULL)
	  temp=temp->next;
	  temp->next=(struct node *)malloc(sizeof(struct node));

	  temp=temp->next;
	  temp->next=NULL;
	 temp->ch=ch;
	 temp->counter=1;
	   }
 }
 int BuildTable::getCharacter(struct node **head,int pos)
 {
   struct node *temp=*head;

	if(*head==NULL)
	  {
	  return NULL;
	  }
	  else
	  {
		 temp=*head;
			 while(temp!=NULL)
			 {
				 pos--;
				 if(pos==0)
				  return temp->ch;
				temp=temp->next;
			 }
	  }
  return NULL;



 }
 void BuildTable::display(struct node *temp)
 {

	while(temp!=NULL)
	{
	 printf("%c\t%d \n",temp->ch,temp->counter);
	 temp=temp->next;
	 }

 }
void BuildTable::replaceNumber(char fname[30])
{
   FILE *fp,*fp1;
   int ch;
	fp=fopen(fname,"r");
	fp1=fopen("c:\Huffnum.txt","w");
	if(fp==NULL||fp1==NULL)
	{
	printf("File Not Found");

	exit(0);
	}
	while((ch=fgetc(fp))!=EOF)
	 fprintf(fp1,"%d",ch);
   fcloseall();
}
int BuildTable:: search(struct node **head,int ch)
{
   struct node *temp=*head;

	if(*head==NULL)
	  {
	  return 1;
	  }
	  else
	  {
	 temp=*head;
	  while(temp!=NULL)
	  {
		if(temp->ch==ch)
		{
		 temp->counter++;
		 return 0;
		}
	  temp=temp->next;
	  }
	   }
  return 1;
}

int BuildTable::getPosition(struct node *temp,int ch)
{
	int pos=0;
	if(temp==NULL)
	  {
	  return 0;
	  }
	  else
	  {
	  while(temp!=NULL)
	   {
	   pos++;
		if(temp->ch==ch)
		{
		 return pos;
		}
	  temp=temp->next;
	  }
	   }
  return 0;
}

void BuildTable:: SortTable(struct node **head)
{
	struct node *temp,*temp1;
	int tempCounter,tempCh;
	int i,j;

  if(*head==NULL)
	return;
  else
  {
	temp=*head;
   while(temp!=NULL)
  {
	 temp1=*head;
	while(temp1!=NULL)
	{
	   if( ( temp1 -> counter ) < ( temp -> counter ) )
		{
		 tempCounter = temp1 -> counter;
		 temp1 -> counter = temp -> counter;
		 temp -> counter = tempCounter;
		 tempCh = temp1 -> ch;
		 temp1 -> ch = temp -> ch;
		 temp -> ch = tempCh;
		}
		 temp1 = temp1 -> next;
	}
	temp=temp->next;
  }
}
}


void  binary_2_number(int ,int );
int ans;
void main()
{
	struct node *head=NULL,*temp;
	BuildTable BT;
	int result,position;
	int ch;
	char fname[50];
	FILE *fp,*fp1;
	printf("Enter File Name:");
	scanf("%s",fname);

	  fp=fopen(fname,"rb");
	 if(fp==NULL)
	 {
	 printf("Error While Openonig  %s",fname);
	 return ;
	 }

	while((ch=fgetc(fp))!=EOF)
	{
	 result=BT.search(&head,ch);/*whether the char is in the table or not
							   if it is in then no need to add that in
							   the table search will automatically
							   increment its count
							   */

	 if(result!=0)
	 BT.create(&head,ch);
	}
   //	BT.display(head);

	 BT.SortTable(&head);   /*This function can sort the nodes according to
						   the occurrences of a charcter
						 */

	//  BT.display(head);
						 /*this function will display the sorted nodes
							can be used for display (those which r not sorted)
							sort it in descending order
						*/
  fclose(fp);
 fp=fopen(fname,"rb");
 fp1=fopen("c:/temp.neo","wb");
 if(fp==NULL||fp1==NULL)
 {
  printf("Could not open file") ;

  return ;
 }
	while((ch=fgetc(fp))!=EOF)
	{
	  position=BT.getPosition(head,ch);
	   if(position==0)
	   {
	   printf("Error During Compression");
	   ;
	   return ;
	   }
		for(;position!=1;position--)
		 fputc('1',fp1);
	   fputc('0',fp1);
	}
fclose(fp1);
fclose(fp);
	fp=fopen("c:/huff.txt","wb");
	if(fp==NULL)
	{
	 printf("Error While Opening huff.txt");
	 ;
	 exit(0);
	}
	temp=head;
	while(temp!=NULL)
	{
	 fputc(temp->ch,fp);
	 temp=temp->next;
	}
	fputc('`',fp);
   fp1=fopen("c:/temp.neo","rb");
	if(fp1==NULL)
	{
	 printf("Error While Opening temp.neo");
	 return ;
	}

   ch=0;
	 while(ch!=EOF)
	 {
	 ans=0;
	  for(int i=7;i>=0;i--)
	   {
		ch=fgetc(fp1);
			if(ch==EOF)
		 break;
 //		printf("i=%d  ch=%d\n",i,ch);
		binary_2_number(ch,i);
  //		printf("  ans=%d",ans);
		   }
	  // printf("%d\n",ans);
	   fputc(ans,fp);
	//   printf("%c  %d\n",ans,ans);
	//   ;

  }
//  fputc(EOF,fp);
fcloseall();
 if(unlink("c:/TEMP.NEO")==0)
 printf("OK");
}


  void  binary_2_number(int ch,int i)
{
   int temp;
   if(ch=='1')
   {
	 temp=pow(2,i);
	// printf("  temp=%d",temp);
	 ans=ans+temp;
   }
   else
	 ans=ans+0;
}
